/*
 * test for improvement of constructor and destructor
 */

#include <stdio.h>
#include <stdlib.h>
#include <string.h>
#include <sys/time.h>

#include "ctor_dtor_test.h"
#include "../slab/mm.h"

/* double word (8) alignment */
#define ALIGNMENT 8

/* rounds up to the nearest multiple of ALIGNMENT */
#define ALIGN(size) (((size) + (ALIGNMENT-1)) & ~0x7)

typedef struct _test_struct
{
    char   str[16];
    FILE*  fp[16];
} test_t;

void ctor(void* p, mem_cache_t* cachep, unsigned int f)
{
    int j = 0;

    test_t* test_tp = (test_t*)p;
    memset(test_tp->str, 'A', 14);
    test_tp->str[14] = '\n';
    test_tp->str[15] = 0;
    for (j=0; j<16; ++j)
    {
        test_tp->fp[j] = fopen("a","r");
    }
}

void dtor(void* p, mem_cache_t* cachep, unsigned int f)
{
    // we do nothing here
}

void run_ctor_dtor_test()
{
    struct timeval time1, time2;
    int i=0, time = 0;
    test_t* test_tp = 0;
    FILE* fp1 = 0;

    fp1 = fopen("test_ctor_dtor","a");
    if (!fp1)
    {
        fprintf(stderr, "can not open file for logging!");
        exit (1);
    }

    srandom(random());

    printf("using libc, please wait...");fflush(stdout);

    gettimeofday(&time1, 0);

    for (i = 0; i<10000; ++i)
    {
        test_tp = malloc(sizeof(test_t));

        ctor(test_tp, 0, 0);

        free(test_tp);
    }

    gettimeofday(&time2, 0);

    printf("done\n");

    time = abs(time2.tv_usec-time1.tv_usec);
    printf("time=%dus\t\tthroughput=%.2g\n",
            time,
            20000.0f*1000000/time);
    fprintf(fp1,"%.4g ",
            20000.0f*1000000/time);

    printf("initializing our slab implementation, please wait...");fflush(stdout);

    mm_init(true);

    printf("done\n");

    printf("using our slab implementation, please wait...");fflush(stdout);

    gettimeofday(&time1, 0);

    mem_cache_create(ALIGN(sizeof(test_t)+4), 0, ctor, dtor);

    //test_tp = mm_malloc(sizeof(test_t));

    // printf("%s", test_tp->str); // you can comment this line, but you can use this line to prove the correctness ;)

    //mm_free(test_tp);

    for (i = 0; i<10000-1; ++i)
    {
        test_tp = mm_malloc(sizeof(test_t));

        // printf("%s", test_tp->str); // you can comment this line, but you can use this line to prove the correctness ;)

        mm_free(test_tp);
    }

    gettimeofday(&time2, 0);

    printf("done\n");

    time = abs(time2.tv_usec-time1.tv_usec);
    printf("time=%dus\t\tthroughput=%.2g\n",
            time,
            20000.0f*1000000/time);
    fprintf(fp1,"%.4g\n",
            20000.0f*1000000/time);

    printf("un-initializing our slab implementation, please wait...");fflush(stdout);

    mm_deinit();

    printf("done\n");

    fclose(fp1);
}
